#include "model/der/Fork.h"
#include "gui/Dibujar/Defines.h"
#include "model/Connector.h"
#include "model/der/ViaDER.h"
#include "model/der/Entity.h"
#include "model/der/Attribute.h"
#include <limits.h>

Fork::Fork(const std::string & name, int orientation)
: ComponentDER(name, orientation) {
	m_padre = NULL;
	initializeConnectors();
}


Fork::Fork(const Fork & otro) : ComponentDER(otro){
	m_padre = NULL;
	initializeConnectors();
}


Fork& Fork::operator=(const Fork& otro) {
	ComponentDER::operator=(otro);
	return *this;
}


void Fork::serialize(XmlWriter & writer_rep, XmlWriter & writer_comp)
{
	writer_rep.addRootChild(TARGET_FORK, "");
	ComponentDER::serialize(writer_rep, writer_comp);
}

void Fork::initializeConnectors() {
	componentType = ComponentTypeDerFork;

	addConnector( FORK_ENTRADA_0, false);
	addConnector( FORK_ENTRADA_1, false);
	addConnector( FORK_ENTRADA_2, false);
	addConnector( FORK_ENTRADA_3, false);
	addConnector( FORK_ENTRADA_13, false);
	addConnector( FORK_ENTRADA_32, false);
	addConnector( FORK_ENTRADA_10, false);
	addConnector( FORK_ENTRADA_20, false);
	addConnector( FORK_ENTRADA_100, false);
	addConnector( FORK_ENTRADA_200, false);
	addConnector( FORK_ENTRADA_1000, false);
	addConnector( FORK_ENTRADA_2000, false);
	m_types.push_back("Generalización");
	m_types.push_back("Especialización");
}

#include <map>

void Fork::update() {
	std::map<Entity *, Connector *> entidadesYConectores;

	m_attributes.clear();
	m_entities.clear();
	for (unsigned i = 0; i < conectoresEntrantes.size(); i++) {
		if (conectoresEntrantes[i]->getVia() != NULL) {
			Via* via = conectoresEntrantes[i]->getVia();
			if (via->getEndConnector() != conectoresEntrantes[i]) {
				if (via->getEndConnector()->isEntry()) {
					Entity *entidad = dynamic_cast<Entity*>(via->getEndConnector()->getFather());
					Connector *conector = via->getEndConnector();
					entidadesYConectores.insert(std::pair<Entity *, Connector *>(entidad, conector));
					m_entities.push_back(entidad);
				} else {
					m_attributes.push_back(dynamic_cast<Attribute*>(via->getEndConnector()->getFather()));
				}
			} else {
				if (via->getStartConnector()->isEntry()) {
					Entity *entidad = dynamic_cast<Entity*>(via->getStartConnector()->getFather());
					Connector *conector = via->getStartConnector();
					entidadesYConectores.insert(std::pair<Entity *, Connector *>(entidad, conector));
					m_entities.push_back(entidad);
				} else {
					m_attributes.push_back(dynamic_cast<Attribute*>(via->getStartConnector()->getFather()));
				}
			}
		}
	}

	unsigned int minY = UINT_MAX;
	m_padre = NULL;
	m_hijos.clear();
	m_conectorAlPadre = NULL;
	m_conectoresALosHijos.clear();

	for (unsigned int i = 0; i < m_entities.size(); i ++) {
		Entity *entity = m_entities[i];
		unsigned int entityY = entity->getY();
		if (entityY < minY) {
			if (m_padre != NULL) {
				m_hijos.push_back(m_padre);
			}
			m_padre = entity;
			minY = entityY;
		} else {
			m_hijos.push_back(entity);
		}
	}

	m_conectorAlPadre = entidadesYConectores[m_padre];
	for (unsigned int i = 0; i < m_hijos.size(); i++) {
		m_conectoresALosHijos.push_back(entidadesYConectores[m_hijos[i]]);
	}
}

std::string Fork::description() {
	this->update();

	std::string d = "";
	d += "FORK ( \n";
	d += "  PADRE: " + (m_padre ? m_padre->getName() : "no tiene") + "\n";
	d += "  HIJOS: \n";
	for (unsigned int i = 0; i < m_hijos.size(); i++) {
		Entity *hijo = m_hijos[i];
		d += "    " + hijo->getName() + ",\n";
	}
	d += ")\n";
	return d;
}

